<div class="tutorial-bundle" data-metadata-json='{"programKind": "per-method", "difficulty": "medium", "groupedProjectAssets": [{"name": "Space aliens", "assets": ["Invader_Navy_1.png", "Invader_Navy_2.png", "Invader_Green_1.png", "Invader_Green_2.png", "Invader_DarkRed_1.png", "Invader_DarkRed_2.png", "Invader_Blue_1.png", "Invader_Blue_2.png", "Invader_Cyan_1.png", "Invader_Cyan_2.png", "Invader_Orange_1.png", "Invader_Orange_2.png", "Invader_Pink_1.png", "Invader_Pink_2.png", "Invader_Red_1.png", "Invader_Red_2.png", "Invader_Yellow_1.png", "Invader_Yellow_2.png"]}, {"name": "Explosion frames", "assets": ["Explosion_1.png", "Explosion_2.png", "Explosion_3.png", "Explosion_4.png", "Explosion_5.png"]}]}' data-tip-sha1="66ca53b0f057f435f3561bfee791d97cc8d9ab40"><div class="front-matter" data-complete-code-text='import pytch
import random


class Stage(pytch.Stage):
    Backdrops = ["galaxy.png"]

    @pytch.when_green_flag_clicked
    def run(self):
        Stage.score = 0
        pytch.show_variable(Stage, "score")
        Stage.lives = 3
        pytch.show_variable(Stage, "lives", right=236)
        pytch.broadcast_and_wait("make-clones")
        pytch.broadcast_and_wait("play-game")


class Alien(pytch.Sprite):
    Costumes = [
        "Invader_Navy_1.png",
        "Invader_Navy_2.png",
        "Invader_Green_1.png",
        "Invader_Green_2.png",
        "Invader_DarkRed_1.png",
        "Invader_DarkRed_2.png",
        "Invader_Blue_1.png",
        "Invader_Blue_2.png",
        "Invader_Cyan_1.png",
        "Invader_Cyan_2.png",
        "Invader_Orange_1.png",
        "Invader_Orange_2.png",
        "Invader_Pink_1.png",
        "Invader_Pink_2.png",
        "Invader_Red_1.png",
        "Invader_Red_2.png",
        "Invader_Yellow_1.png",
        "Invader_Yellow_2.png"
    ]

    @pytch.when_I_receive("make-clones")
    def make_clones(self):
        self.go_to_xy(-150, 180)
        pytch.create_clone_of(self)
        self.go_to_xy(-90, 180)
        pytch.create_clone_of(self)
        self.go_to_xy(-30, 180)
        pytch.create_clone_of(self)
        self.go_to_xy(30, 180)
        pytch.create_clone_of(self)
        self.go_to_xy(90, 180)
        pytch.create_clone_of(self)
        self.go_to_xy(150, 180)

    @pytch.when_I_receive("play-game")
    def drift_down_screen(self):
        self.set_size(0.15)
        while Stage.lives &gt; 0:
            costume_index = random.choice([0, 2])
            self.switch_costume(costume_index)
            self.set_y(180)
            self.show()
            glide_time = random.uniform(3.0, 5.0)
            self.glide_to_xy(self.x_position, -180, glide_time)

    @pytch.when_this_sprite_clicked
    def handle_hit(self):
        if self.costume_number == 0:
            Stage.score += 10
        if self.costume_number == 2:
            Stage.lives -= 1
            if Stage.lives == 0:
                pytch.broadcast("game-over")

        self.hide()

    @pytch.when_I_receive("game-over")
    def do_game_over(self):
        self.hide()
' data-initial-code-text='import pytch
import random


class Stage(pytch.Stage):
    Backdrops = ["solid-white.png"]
'><h1>Blue Invaders</h1><p>In this game, the player will defend earth from dangerous blue
invaders, by clicking on them.  But they must not destroy the friendly
green aliens by mistake!</p></div><div class="chapter-content"><h2>Set the backdrop</h2><p>The first job is to make the background for our game.  Pytch’s media
library includes a galaxy image for us to use.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add the “galaxy” backdrop to the Stage from the media library.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-medialib-appearances-entry", "actor": {"kind": "stage"}, "displayIdentifier": "galaxy.png", "nItems": 1}' data-slug="add-starry-backdrop"></div>
</div></div><p>If you run your game now, you won’t see your new background.  This is
because the Stage still has the default solid white background, and
that background is the first one, so it is the one that gets shown.</p><div class="learner-task"><div class="learner-task-intro">
<p>Delete the <code>solid-white.png</code> backdrop from the stage.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "delete-appearance", "actor": {"kind": "stage"}, "appearanceFilename": "solid-white.png"}' data-slug="remove-white-backdrop"></div>
</div></div><p>Click on the green play button now — you should see the game’s
new background.</p></div><div class="chapter-content"><h2>Create the first alien</h2><p>When it’s finished, the game will have lots of aliens, but to start
with, there will just be one.</p><p>There will be an <code>Alien</code> Sprite which will have different costumes.
When this sprite is wearing one costume (a blue one), it counts as an
enemy space invader, and when it’s wearing another costume (a green
one), it’s a friendly visitor.</p><h3>Create <em>Alien</em> Sprite</h3><p>The project needs a new sprite to be the Alien.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a Sprite called <code>Alien</code> to your project.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-sprite", "name": "Alien"}' data-slug="create-alien-sprite"></div>
</div></div><h3>Give the <em>Alien</em> some costumes</h3><p>The new sprite then needs costumes.  There is a bundle of
suitable costumes in Pytch’s media library.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add the ‘Space aliens’ bundle of images from the media library as
costumes to the <code>Alien</code> sprite.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-medialib-appearances-entry", "actor": {"kind": "sprite", "name": "Alien"}, "displayIdentifier": "Space aliens", "nItems": 18}' data-slug="add-alien-costumes"></div>
</div></div><p>If you run your project now, you should see a blue enemy invader in
the middle of the screen.  This is because Pytch starts a Sprite off
wearing its first costume.</p><div class="learner-task"><div class="learner-task-intro">
<p>Try your game.  What's wrong?</p>
</div><div class="learner-task-help">
<p>The alien is way too big!</p>
</div></div><h3>Make the alien a sensible size</h3><p>The very first thing the alien needs to do is set its size to
something more sensible.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a new empty script to the <code>Alien</code> with a “when green flag clicked”
hat-block.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "green-flag"}, "codeText": ""}' data-slug="add-drift-down-skeleton"></div>
</div></div><p>The code in this script needs to set the Alien’s size.  In Pytch, a
size of <code>1</code> means original size, <code>0.5</code> means half size, and so on.
You can check that a size of <code>0.15</code> is about right.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add code to your script which sets the Alien’s size to <code>0.15</code>.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "green-flag"}, "oldCodeText": "", "newCodeText": "self.set_size(0.15)"}' data-slug="set-Alien-size"></div>
</div></div><h3>Make the alien drift down the screen</h3><p>The Alien should glide from the top to the bottom of the screen, then
instantly go back to the top and start gliding again.</p><p>You can add code to your script which works the same as Scratch’s
<em>forever</em> block.  In Python, you can say <code>while True:</code>, and underneath
put <em>indented</em> lines to say what should keep happening.</p><p>For example, here’s code which moves a sprite slowly across the screen:</p><pre><code class="language-python">while True:
    self.change_x(1)
</code></pre><div class="learner-task"><div class="learner-task-intro">
<p>Add code to the end of your script which makes the alien repeatedly go
to the top of the screen then glide to the bottom.</p>
</div><div class="learner-task-help">
<p>To tell the alien to go to a particular vertical place on the screen,
you can use something like</p>
<pre><code class="language-python">self.set_y(50)
</code></pre>
<p>The number <code>50</code> here is the <em>y</em> coordinate the alien should go to.
Its <em>x</em> coordinate is not changed.  The alien will move purely up or
down.</p>
</div><div class="learner-task-help">
<p>To tell the alien to move smoothly to a different place on the screen, you can
use something like</p>
<pre><code class="language-python">self.glide_to_xy(0, -50, 2.5)
</code></pre>
<p>The numbers are the <em>x</em> and <em>y</em> coordinates of the point the alien
should go to, and how long to take (the number of seconds) to move
there.  You might find it useful to use</p>
<pre><code class="language-python-expression">self.x_position
</code></pre>
<p>instead of an actual <em>x</em> number, looking ahead to when there are lots
of aliens, each with its own <em>x</em> position.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "green-flag"}, "oldCodeText": "self.set_size(0.15)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)"}' data-slug="add-drift-down-body"></div>
</div></div></div><div class="chapter-content"><h2>Mixture of enemy and friendly aliens</h2><p>Some of the aliens that drift down the screen need to be enemies, and
some friendly.  Remember that this is done by making the alien wear a
different costume.</p><p>Just like in Scratch, you can switch costume either by giving the new
costume’s place in the costumes list, or by giving its name.  In this
case it will be slightly easier to choose the costume by its place in
the list.  You can look in the “Costumes” tab to see what costumes are
available and in what order.</p><p>In Python:</p><ul>
<li>people use the word <em>index</em> to say what position something has in a
  list;</li>
<li>things in a list are numbered from <em>zero</em>, so the first
  thing in a list is at ‘index 0’, the second thing is at
  ‘index 1’, and so on.</li>
</ul><p>For our aliens, the costumes at index 0 and index 2 are the
right ones, so the code should randomly choose between these two
numbers.</p><p>This <em>could</em> be done all in one line of code, but breaking the job
into two steps will make it easier to understand:</p><ul>
<li>Randomly choose a costume index (0 or 2).</li>
<li>Switch to the chosen costume.</li>
</ul><h3>Randomly choose which costume</h3><p>The <code>random.choice(list_of_choices)</code> function will do this job.</p><p>The <code>random.choice()</code> function needs a <em>list</em> of the options it should
choose from.  Here, the choices are <code>0</code> and <code>1</code>.  In Python, the list
containing <code>0</code> and <code>2</code> is written <code>[0, 2]</code>.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a line of code which randomly chooses <code>0</code> or <code>2</code> to be the
index of the new costume, and stores the choice in a variable
called <code>costume_index</code>.</p>
</div><div class="learner-task-help">
<p>The new code should go at the top of the indented body of the <code>while
True</code> loop.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "green-flag"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)"}' data-slug="choose-random-costume"></div>
</div></div><h3>Switch to chosen costume</h3><p>Once the chosen number is in a variable, the alien can switch to that
costume.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a line of code which switches to the costume whose index is in
the variable <code>costume_index</code>.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "green-flag"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)"}' data-slug="switch-to-chosen-costume"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Try your game.  If you run the project, you should see aliens gliding
down the screen.  There should be a random mixture of blue ones and
green ones.</p>
</div></div></div><div class="chapter-content"><h2>Make lots of aliens</h2><p>To make more than one alien, the program will use <em>clones</em>.  These
work the same as in Scratch — you get more than one copy of the same
sprite.</p><p>The program will clone the Alien five times.  Together with the
original Alien, this makes six aliens altogether.</p><p>Using the <em>x</em>-positions</p><blockquote>
<p>-150, -90, -30, 30, 90, and 150</p>
</blockquote><p>will spread the aliens left to right across the screen.</p><p>The idea is:</p><ul>
<li>Move the original Alien to the first place (<em>x</em>-position of <code>-150</code>).</li>
<li>Make a clone at that position, then move the original to the next
  place (<code>x = -90</code>).</li>
<li>Make another clone, and move the original to <code>x = -30</code>.</li>
<li>And so on.</li>
</ul><div class="learner-task"><div class="learner-task-intro">
<p>Add an empty <em>green-flag</em> script to the Alien.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "make_clones"}, "event": {"kind": "green-flag"}, "codeText": ""}' data-slug="add-make-clones-script"></div>
</div></div><p>This script now needs code to make and move the clones.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a line of code to this script which moves the alien to the place
on the stage with <em>x</em>-position <code>-150</code> and <em>y</em>-position <code>180</code>.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "make_clones"}, "event": {"kind": "green-flag"}, "oldCodeText": "", "newCodeText": "self.go_to_xy(-150, 180)"}' data-slug="move-first-alien-to-position"></div>
</div></div><div class="learner-task"><div class="learner-task-intro">
<p>Add two lines of code to this script.  The first line should make a
clone of the Alien.  The second line should move the original Alien to
the place on the stage with <em>x</em>-position <code>-90</code> and <em>y</em>-position <code>180</code>.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "make_clones"}, "event": {"kind": "green-flag"}, "oldCodeText": "self.go_to_xy(-150, 180)", "newCodeText": "self.go_to_xy(-150, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-90, 180)"}' data-slug="make-first-clone"></div>
</div></div><div class="learner-task"><div class="learner-task-intro">
<p>Add the rest of the required code, which will be very similar to
copies of the lines you’ve just added.  You should end up with clones
at <em>x</em>-positions</p>
<blockquote>
<p>-150, -90, -30, 30, and 90</p>
</blockquote>
<p>and the original Alien at <em>x</em>-position 150.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "make_clones"}, "event": {"kind": "green-flag"}, "oldCodeText": "self.go_to_xy(-150, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-90, 180)", "newCodeText": "self.go_to_xy(-150, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-90, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-30, 180)\npytch.create_clone_of(self)\nself.go_to_xy(30, 180)\npytch.create_clone_of(self)\nself.go_to_xy(90, 180)\npytch.create_clone_of(self)\nself.go_to_xy(150, 180)"}' data-slug="make-rest-of-clones"></div>
</div></div><p>(You might be thinking that there must be a better way to do this than
by copy and pasting nearly identical code.  You’re right, but that’s
outside the scope of this tutorial!)</p><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Try your game.  What happens?</p>
</div><div class="learner-task-help">
<p>More aliens do appear, but only one of them moves.</p>
</div></div><h3>It doesn’t work properly!</h3><p>If you run the game now, it doesn’t really work.  There are more
aliens at the top of the screen, but only one of them is gliding down.
This is because Pytch doesn’t make any guarantees about which order
the two <em>green-flag</em> scripts run, and the glide script is happening
before all the clones are made.</p><p>The next chapter explains how to fix this.</p></div><div class="chapter-content"><h2>Using broadcasts to control when scripts run</h2><p>To make sure that everything happens in the right order, the program
will use another part of Pytch which might be familiar from Scratch —
<em>broadcasts</em>.  A sprite can ‘shout’ a message, and any sprite
(including the same sprite that shouted!) can be listening for that
message, and run some code whenever the sprite hears the message.</p><p>The program needs to make sure that all the clones are made before the
gliding starts.  The Stage will be in charge of making this happen.</p><p>Because the program will use broadcasts to coordinate things, the
script you just wrote, which makes all the clones, needs to run when
it receives an appropriate broadcast message.</p><div class="learner-task"><div class="learner-task-intro">
<p>Make the script which creates all the clones run when the Alien
receives the <code>"make-clones"</code> message (not when green flag is clicked).</p>
</div><div class="learner-task-help">
<p>The code stays the same.  You just need to change the script’s hat
block.  This is like when, in Scratch, you get rid of a script’s hat
block and attach a different one.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "change-hat-block", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "make_clones"}, "codeText": "self.go_to_xy(-150, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-90, 180)\npytch.create_clone_of(self)\nself.go_to_xy(-30, 180)\npytch.create_clone_of(self)\nself.go_to_xy(30, 180)\npytch.create_clone_of(self)\nself.go_to_xy(90, 180)\npytch.create_clone_of(self)\nself.go_to_xy(150, 180)", "oldEvent": {"kind": "green-flag"}, "newEvent": {"kind": "message-received", "message": "make-clones"}}' data-slug="make-clones-when-receive"></div>
</div></div><div class="learner-task"><div class="learner-task-intro">
<p>Add a <em>green-flag</em> script <strong>to the stage</strong> which broadcasts this
<code>"make-clones"</code> message, and waits for the listening scripts to finish
running.  Adding the script to the stage makes sense because that’s a
central place to put all high-level control code.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "codeText": "pytch.broadcast_and_wait(\"make-clones\")"}' data-slug="broadcast-make-clones"></div>
</div></div><h3>Wait for all clones to exist before gliding</h3><p>The code you just added uses <code>broadcast_and_wait()</code>.  Just like in
Scratch, your program doesn’t go on to the next statement until
everybody listening for the <code>"make-clones"</code> message has finished doing
whatever it is they do when they hear it.  So any code after
<code>broadcast_and_wait()</code> won’t run until all the clones exist.</p><p>This is how the program can control when the aliens start gliding.</p><div class="learner-task"><div class="learner-task-intro">
<p>Change your program so the gliding code in the <code>Alien</code> sprite runs
when an alien or clone hears a <code>"play-game"</code> message (and not when the
green flag is clicked).</p>
</div><div class="learner-task-help">
<p>Just like a minute ago, the code stays the same.  You just need to
change the script’s hat block.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "change-hat-block", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "codeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)", "oldEvent": {"kind": "green-flag"}, "newEvent": {"kind": "message-received", "message": "play-game"}}' data-slug="descend-on-play-game-broadcast"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Try your game.  What happens?  Why?</p>
</div><div class="learner-task-help">
<p><em>All</em> the aliens just stay at the top of the screen.  The gliding code
only runs when somebody broadcasts the <code>"play-game"</code> message, and
nobody is doing that.</p>
</div></div><p>Now you can add code to the correct place which broadcasts the message
the aliens are waiting for.</p><div class="learner-task"><div class="learner-task-intro">
<p>Make the Stage broadcast that <code>"play-game"</code> message, once the clones
have all been created.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "oldCodeText": "pytch.broadcast_and_wait(\"make-clones\")", "newCodeText": "pytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")"}' data-slug="broadcast-play-game"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your project.  You should see waves of aliens gliding down the
screen, a mixture of blue and green each time.  (Sometimes, just by
chance, you’ll get an all-blue wave or an all-green one.)</p>
</div></div><p>This is OK, but it would be better if some aliens went faster than
others.</p></div><div class="chapter-content"><h2>Randomise the glide time</h2><p>At the moment, every alien clone takes exactly 3 seconds to glide
down the screen.  The game would be better with a bit of variation, by
making each alien clone take a random time to glide down the screen.
This will make some aliens move faster than others and make it more
interesting.</p><p>The Alien’s <code>"play-game"</code> code needs changing so that each alien takes
a random time between, say, 3 and 5 seconds.</p><p>Your program already uses <code>random.choice()</code>.  Python also provides the
<code>random.uniform()</code> function, which picks a random number anywhere
between two limits.  Your program can use this to get a random number
anywhere between 3.0 and 5.0 (including fractions).</p><div class="learner-task"><div class="learner-task-intro">
<p>In the Alien’s <code>"play-game"</code> script, add a line of code just before
the <code>self.glide_to_xy()</code> which uses <code>random.uniform()</code> to get a random
number anywhere between 3 and 5 and assigns the result to a variable
called <code>glide_time</code>.</p>
</div><div class="learner-task-help">
<p>The Python expression</p>
<pre><code class="language-python-expression">random.uniform(3.0, 5.0)
</code></pre>
<p>will generate the random number you want.</p>
</div><div class="learner-task-help">
<p>Remember you used the code</p>
<pre><code class="language-python">costume_index = random.choice([0, 2])
</code></pre>
<p>to make a random choice from the list <code>[0, 2]</code>, and assigns the result
to the variable <code>costume_index</code>.  You want to do something similar.</p>
</div><div class="learner-task-help">
<p>Here you want a random number anywhere between 3 and 5, including
fractional part.  The</p>
<pre><code class="language-python-expression">random.uniform()
</code></pre>
<p>function will do this for you.  Look in the help to see how to use it.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "message-received", "message": "play-game"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.glide_to_xy(self.x_position, -180, 3.0)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, 3.0)"}' data-slug="define-glide-time"></div>
</div></div><p>Now you can use this variable to say how long the gliding motion
should take.</p><div class="learner-task"><div class="learner-task-intro">
<p>Change the existing code to use this new <code>glide_time</code> variable instead
of the fixed number <code>3.0</code> in the <code>glide_to_xy()</code> function call.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "message-received", "message": "play-game"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, 3.0)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, glide_time)"}' data-slug="use-glide-time"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your project.  You should see some aliens falling faster than
others, and after little while it looks almost like aliens are
appearing at random.</p>
</div></div></div><div class="chapter-content"><h2>Click on the aliens!</h2><p>Now your project is quite nice to look at, but it isn’t a <em>game</em>
because there’s nothing for the player to do.  That’s the next job.</p><h3>React when hit</h3><p>The Aliens (original and clones) should react when they’re clicked on
by the player.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a <em>when-this-sprite-clicked</em> script to your Alien.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "codeText": ""}' data-slug="add-when-hit-skeleton"></div>
</div></div><p>Now you have the script, you need to write its code.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add code to your new script which makes the Alien hide itself.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "oldCodeText": "", "newCodeText": "self.hide()"}' data-slug="hide-when-hit"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  Check you can click on the aliens to make them
disappear.</p>
</div></div><p>But now there’s a different problem — once the player has clicked on
an alien, that alien doesn’t appear again.</p><h3>Re-appear at the top of the screen</h3><p>Each alien must make sure it’s visible just before it starts
gliding down the screen.</p><div class="learner-task"><div class="learner-task-intro">
<p>Think about where in your Alien’s code you need to make sure each
Alien is visible, and add code to do this.</p>
</div><div class="learner-task-help">
<p>Remember that the Aliens’ movement is controlled by code in the
<code>"play-game"</code> script.</p>
</div><div class="learner-task-help">
<p>A good place to make the Alien show itself is after it has chosen a
random costume and moved to the top of the screen, but before the code
which makes the Alien glide down the screen.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "message-received", "message": "play-game"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, glide_time)", "newCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.show()\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, glide_time)"}' data-slug="show-when-starting-descent"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  Aliens should constantly reappear after you click on
them.</p>
</div></div></div><div class="chapter-content"><h2>Keep score</h2><p>To let the player know how they’re doing, the game should keep score.
Just like in Scratch, your program remembers numbers (or strings, or
lists, or anything else) using a <em>variable</em>.  In Python, you don’t
have to explicitly make a variable.  Setting a new variable to a value
creates that variable for you.</p><h3>Initialise score to zero</h3><p>The Stage will keep track of the player’s score, in a variable which
belongs to the Stage.</p><p>For example, to create a variable <code>time</code> belonging to the Stage,
setting it to the value <code>60</code>, the code would be</p><pre><code class="language-python">Stage.time = 60
</code></pre><div class="learner-task"><div class="learner-task-intro">
<p>Use this example to write code which sets a Stage variable <code>score</code> to
the value <code>0</code>.  This variable should be created when your program
starts running, so think about where your code should be added.</p>
</div><div class="learner-task-help">
<p>To make sure the new code runs at the start of the game, it should go
at the top of the Stage’s <em>green-flag</em> script.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "oldCodeText": "pytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")", "newCodeText": "Stage.score = 0\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")"}' data-slug="define-global-score"></div>
</div></div><h3>Show score</h3><p>In Scratch, you tick a box to say that you want the variable to be
shown.  In Pytch you do this by writing some code.  The Stage’s
<code>score</code> variable should be shown as soon as the game starts, just
after the variable is created.</p><p>For example, to show a variable <code>time</code> belonging to the Stage, the
code would be</p><pre><code class="language-python">pytch.show_variable(Stage, "time")
</code></pre><p>The way this works is unusual — you use the <em>name</em> of the variable,
written as a <em>string</em>.  The reason for this is outside the scope of
this tutorial!</p><div class="learner-task"><div class="learner-task-intro">
<p>Add code which shows the Stage’s <code>score</code> variable.  Think about where
that code should go.</p>
</div><div class="learner-task-help">
<p>The code should go straight after the code which creates the
<code>Stage.score</code> variable.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "oldCodeText": "Stage.score = 0\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")", "newCodeText": "Stage.score = 0\npytch.show_variable(Stage, \"score\")\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")"}' data-slug="show-score"></div>
</div></div><h3>Give points for hitting an enemy</h3><p>Let’s give the player 10 points when they click on an enemy
invader.  There is already some code which makes the Aliens hide
themselves when it’s clicked, so this is a good place to add the code
which updates the score.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add code which gives the player ten points whenever they click on
<em>any</em> alien.  (In a minute you’ll change this code so only enemy
aliens give you points.)</p>
</div><div class="learner-task-help">
<p>In Scratch, the code</p>
<pre><code class="language-scratch">change [score v] by (10)
</code></pre>
<p>adds <code>10</code> to a variable called <code>score</code>.  Look in the help (use the
‘question mark in circle’ icon at the top of the activity bar to show it)
to find how to do the same thing in Python.  Remember the variable you
want to change is <code>Stage.score</code>.</p>
</div><div class="learner-task-help">
<p>The Python code to do this job is</p>
<pre><code class="language-python">Stage.score += 10
</code></pre>
<p>Think about where to add this code.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "oldCodeText": "self.hide()", "newCodeText": "Stage.score += 10\n\nself.hide()"}' data-slug="award-score-on-any-hit"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  Check you get 10 points for every alien you click.</p>
</div></div><h3>Only get points for enemy aliens</h3><div class="learner-task"><div class="learner-task-intro">
<p>Move this code so it is ‘inside an <code>if</code> test’ — only give the player
points if it’s an enemy alien.</p>
</div><div class="learner-task-help">
<p>You can test whether it’s an enemy alien by checking whether the
costume number is zero.</p>
</div><div class="learner-task-help">
<p>In Scratch, you would write code like</p>
<pre><code class="language-scratch">if &lt;(costume_number) = (0)&gt; then
  change [score v] by (10)
</code></pre>
<p>Look in the help to find how to do the same thing in Python.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "oldCodeText": "Stage.score += 10\n\nself.hide()", "newCodeText": "if self.costume_number == 0:\n    Stage.score += 10\n\nself.hide()"}' data-slug="award-score-just-for-enemy"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  You should get 10 points for every blue enemy you
click on, and nothing for clicking on a green alien.</p>
</div></div></div><div class="chapter-content"><h2>Count lives</h2><p>The game is quite good now, but there’s nothing to discourage the
player from just clicking everywhere.  There’s no penalty for hitting
a friendly alien.</p><p>The player will have three lives.  Destroying a friendly alien will
cost a life.</p><h3>Keeping track of lives</h3><p>A variable will store how many lives the player has.  The code will be
very similar to the code you wrote to make and show the <code>score</code>
variable.</p><div class="learner-task"><div class="learner-task-intro">
<p>Using the <code>Stage.score</code> variable as an example, create a variable
<code>Stage.lives</code> which has the value <code>3</code> at the start of the game.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "oldCodeText": "Stage.score = 0\npytch.show_variable(Stage, \"score\")\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")", "newCodeText": "Stage.score = 0\npytch.show_variable(Stage, \"score\")\nStage.lives = 3\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")"}' data-slug="define-global-lives"></div>
</div></div><p>The player needs to be able to see how many lives they have.  The
‘lives’ display must not be on top of where the ‘score’ display is,
though.  The <code>pytch.show_variable()</code> function can be told where to put
the display.</p><p>For example, to show a variable <code>Stage.time</code> at the top right of the
stage, the code would be</p><pre><code class="language-python">pytch.show_variable(Stage, "time", right=236)
</code></pre><div class="learner-task"><div class="learner-task-intro">
<p>Show the <code>Stage.lives</code> variable at the top right of the stage.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "stage"}, "methodName": "run"}, "event": {"kind": "green-flag"}, "oldCodeText": "Stage.score = 0\npytch.show_variable(Stage, \"score\")\nStage.lives = 3\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")", "newCodeText": "Stage.score = 0\npytch.show_variable(Stage, \"score\")\nStage.lives = 3\npytch.show_variable(Stage, \"lives\", right=236)\npytch.broadcast_and_wait(\"make-clones\")\npytch.broadcast_and_wait(\"play-game\")"}' data-slug="show-lives"></div>
</div></div><p>And finally your program should take one life away whenever the player
clicks on a friendly alien.</p><div class="learner-task"><div class="learner-task-intro">
<p>In its <em>when clicked</em> script, your Alien already has code which gives
the player points but only if that Alien is wearing the ‘enemy’
costume (i.e., costume number <code>0</code>).</p>
<p>Add similar code which subtracts one life but only if that Alien is
wearing the ‘friendly’ costume (i.e., costume number <code>2</code>).</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "oldCodeText": "if self.costume_number == 0:\n    Stage.score += 10\n\nself.hide()", "newCodeText": "if self.costume_number == 0:\n    Stage.score += 10\nif self.costume_number == 2:\n    Stage.lives -= 1\n\nself.hide()"}' data-slug="decrement-lives-if-friendly"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  You should see the <code>lives</code> display go down each time
you click on a green alien.</p>
<p><strong>There’s a bug — what is it?</strong></p>
</div><div class="learner-task-help">
<p>The game doesn’t stop when you run out of lives.</p>
</div></div><p>Although the player loses a life when they click a friendly alien, the
game keeps going even once the player has lost all their lives.  You
will fix this in the next chapter.</p></div><div class="chapter-content"><h2>End game when no lives left</h2><p>The last piece of work is to make the game stop when the player has
used all their lives.  Your program can tell when this has happened
because the <code>Stage.lives</code> variable will be zero.</p><h3>Stop aliens gliding when game is over</h3><p>First, aliens should stop gliding down the screen once the game is
over.  At the moment, they glide forever, because of the <code>while True</code>.
Instead, they should only glide while the player has some lives left.</p><div class="learner-task"><div class="learner-task-intro">
<p>The ‘condition’ of the <code>while</code> loop is currently just the constant
<code>True</code>, which means the <code>while</code> loop runs forever.</p>
<p>Replace <code>True</code> with a comparison which tests whether the player has
more than zero lives left.</p>
</div><div class="learner-task-help">
<p>You can find out whether the number of lives is greater than zero with
the Python expression</p>
<pre><code class="language-python-expression">Stage.lives &gt; 0
</code></pre>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "drift_down_screen"}, "event": {"kind": "message-received", "message": "play-game"}, "oldCodeText": "self.set_size(0.15)\nwhile True:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.show()\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, glide_time)", "newCodeText": "self.set_size(0.15)\nwhile Stage.lives &gt; 0:\n    costume_index = random.choice([0, 2])\n    self.switch_costume(costume_index)\n    self.set_y(180)\n    self.show()\n    glide_time = random.uniform(3.0, 5.0)\n    self.glide_to_xy(self.x_position, -180, glide_time)"}' data-slug="stop-descent-loop-when-game-over"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  Deliberately click on three green aliens.  You should
see that no more aliens appear.  Instead, aliens stop at the bottom of
the screen.</p>
</div></div><p>But any aliens which are part-way down the screen keep going until
they reach the bottom.  This needs fixing too.</p><p>All aliens should disappear immediately when the player’s lives goes
to zero.  Broadcasting a message when all the player’s lives are gone
will achieve this.</p><div class="learner-task"><div class="learner-task-intro">
<p>After subtracting one from <code>Stage.lives</code>, check whether <code>Stage.lives</code>
is zero.  If it is, broadcast the message <code>"game-over"</code>.</p>
</div><div class="learner-task-help">
<p>You will need an <code>if</code> statement.  For the “condition”, you can ask
whether the player’s lives are all gone with the test</p>
<pre><code class="language-python-expression">Stage.lives == 0
</code></pre>
<p>Notice there are two equals signs there!</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "edit-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "handle_hit"}, "event": {"kind": "clicked"}, "oldCodeText": "if self.costume_number == 0:\n    Stage.score += 10\nif self.costume_number == 2:\n    Stage.lives -= 1\n\nself.hide()", "newCodeText": "if self.costume_number == 0:\n    Stage.score += 10\nif self.costume_number == 2:\n    Stage.lives -= 1\n    if Stage.lives == 0:\n        pytch.broadcast(\"game-over\")\n\nself.hide()"}' data-slug="broadcast-game-over"></div>
</div></div><h3>Test it!</h3><div class="learner-task"><div class="learner-task-intro">
<p>Run your game.  Deliberately click on three green aliens.  What happens?</p>
</div><div class="learner-task-help">
<p>Nothing really!</p>
</div></div><p>Nothing really happens when this code runs, because nobody is
<em>listening</em> for this message.</p><div class="learner-task"><div class="learner-task-intro">
<p>Add a script to the Alien which runs when the message <code>"game-over"</code> is
broadcast.  Inside that script, write a line of code to hide the
alien.</p>
</div><div class="learner-task-help">
<div class="jr-commit" data-jr-commit='{"kind": "add-script", "path": {"actor": {"kind": "sprite", "name": "Alien"}, "methodName": "do_game_over"}, "event": {"kind": "message-received", "message": "game-over"}, "codeText": "self.hide()"}' data-slug="hide-when-receive-game-over"></div>
</div></div><h3>Game complete!</h3><p>Test your game now and make sure it works properly.</p></div><div class="chapter-content"><h2>Challenges and questions</h2><p>Here are some ways you could make the game even better:</p><ul>
<li>
<p>Make the aliens move more quickly as the player’s score goes up.</p>
</li>
<li>
<p>Add a rare red alien which is worth 50 points.  The “Space aliens”
  bundle of images, which you added to the project, includes a red
  alien.  It also includes lots of other colours if you want to choose
  a different one!</p>
</li>
<li>
<p>Add some left-to-right randomness to where the aliens start.</p>
</li>
</ul><p>You can also think about these questions:</p><ul>
<li>Do you agree that the stage is the right place for the main control
  script (the one that broadcasts the messages)?  Does the game still
  work if this script is in the Alien?</li>
</ul><h3>Credits</h3><p>This project was loosely inspired by the <em>Red Alert</em> game in the DK
book <a href="https://www.dk.com/us/book/9781465473615-coding-games-in-python/"><em>Coding Games in
Python</em></a>.</p><h3>Detailed credits</h3><div class="asset-credits"><p class="credit-intro">For <code class="asset-filename">Invader_Blue_1.png</code>, <code class="asset-filename">Invader_Blue_2.png</code>, <code class="asset-filename">Invader_Cyan_1.png</code>, <code class="asset-filename">Invader_Cyan_2.png</code>, <code class="asset-filename">Invader_DarkRed_1.png</code>, <code class="asset-filename">Invader_DarkRed_2.png</code>, <code class="asset-filename">Invader_Green_1.png</code>, <code class="asset-filename">Invader_Green_2.png</code>, <code class="asset-filename">Invader_Navy_1.png</code>, <code class="asset-filename">Invader_Navy_2.png</code>, <code class="asset-filename">Invader_Orange_1.png</code>, <code class="asset-filename">Invader_Orange_2.png</code>, <code class="asset-filename">Invader_Pink_1.png</code>, <code class="asset-filename">Invader_Pink_2.png</code>, <code class="asset-filename">Invader_Red_1.png</code>, <code class="asset-filename">Invader_Red_2.png</code>, <code class="asset-filename">Invader_Yellow_1.png</code>, <code class="asset-filename">Invader_Yellow_2.png</code> (used in the project):</p><div class="credits"><p>The space-alien images are Copyright 2024 Trinity College Dublin.  You
are welcome to use them under the terms of the Creative Commons
Attribution-ShareAlike 4.0 International license.</p></div><p class="credit-intro">For <code class="asset-filename">Explosion_1.png</code>, <code class="asset-filename">Explosion_2.png</code>, <code class="asset-filename">Explosion_3.png</code>, <code class="asset-filename">Explosion_4.png</code>, <code class="asset-filename">Explosion_5.png</code> (used in the project):</p><div class="credits"><p>The explosion images are Copyright 2024 Trinity College Dublin.  You
are welcome to use them under the terms of the Creative Commons
Attribution-ShareAlike 4.0 International license.</p></div><p class="credit-intro">For <code class="asset-filename">galaxy.png</code> (used in the project):</p><div class="credits"><p>The galaxy background image is Copyright 2024 Trinity College Dublin.
You are welcome to use it under the terms of the Creative Commons
Attribution-ShareAlike 4.0 International license.</p></div><p class="credit-intro">For <code class="asset-filename">screenshot.png</code> (used in the tutorial text/summary):</p><div class="credits"><p>The screenshot image is Copyright 2024 Trinity College Dublin.  You
are welcome to use it under the terms of the Creative Commons
Attribution-ShareAlike 4.0 International license.</p></div></div></div></div>